package com.example.esdemo.rabbitmq;

import com.example.esdemo.constants.RabbitConstant;
import com.example.esdemo.es.services.EsPostService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * rabbitmq 消费者
 *
 * @author Cary
 * @date 2022/6/21
 */
@Slf4j
@Component
@RabbitListener(queues = RabbitConstant.ES_QUEUE)
public class ESMqHandler {
    @Autowired
    private EsPostService esPostService;

    @RabbitHandler
    public void handler(ESMqMessage msg, Channel channel, Message message) throws IOException {
        log.info("[Rabbitmq]收到一条消息：{}", msg);
        try {
            switch (msg.getAction()) {
                case ESMqMessage.CREATE_OR_UPDATE:
                    esPostService.createOrUpdateIndex(msg);
                    break;
                case ESMqMessage.REMOVE:
                    esPostService.removeIndex(msg);
                    break;
                default:
                    log.error("[Rabbitmq]没找到对应的消息类型：{}", msg);
                    break;
            }
            /*
             * 消息确认
             * deliveryTag：表示消息投递序号
             * multiple：是否批量确认，值为 true 则会一次性 ack 所有小于当前消息 deliveryTag 的消息。
             */
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            if (message.getMessageProperties().getRedelivered()) {
                log.error("[Rabbitmq]消息已重复处理失败,拒绝再次接收：{}", msg);
                /*
                 * 拒绝消息
                 * deliveryTag：表示消息投递序号。
                 * requeue：值为 true 消息将重新入队列。
                 */
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                log.error("[Rabbitmq]消息即将再次返回队列处理：{}", msg);
                /*
                 * 失败确认
                 * deliveryTag：表示消息投递序号。
                 * multiple：是否批量确认。
                 * requeue：值为 true 消息将重新入队列。
                 */
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }
    }
}
